/*******************************************************************
    Glow tube Clock 

    For use with the ESP32 
 *                                                                 *
    Written by 大玉菌   
 *******************************************************************/

#include <Arduino.h>
#include <TFT_eSPI.h> 
#include <RX8025.h>
#include <WiFi.h>
//#include <NTPClient.h>
#include <time.h>
#include "Image.h"
#include <FastLED.h>            // 此示例程序需要使用FastLED库
 
#define NUM_LEDS 6             // LED灯珠数量
#define LED_DT 16                // Arduino输出控制信号引脚
CRGB leds[NUM_LEDS];            // 建立光带leds

TFT_eSPI tft = TFT_eSPI();
RX8025 rtc;

uint8_t buttonCS1 = 33;
uint8_t buttonCS2 = 17;
uint8_t buttonCS3 = 2;
uint8_t buttonCS4 = 18;
uint8_t buttonCS5 = 5;
uint8_t buttonCS6 = 23;

uint8_t buttonKEY1 = 34;
uint8_t buttonKEY2 = 35;
uint8_t buttonKEY3 = 32;
uint8_t buttonKEY4 = 27;

uint8_t buttonKEY[4];

typedef struct{
int year;
int month;
int day;
int hour;
int minute;
int second;
}timeInfo_t; 

typedef struct 
{
  int hour_h;
  int hour_l;
  int minute_h;
  int minute_l;
  int second_h;
  int second_l;  
}display_time_t;

typedef struct
{
  uint8_t count;    //延时消抖
  uint8_t status;   //有按下的状态
  uint8_t press;    //按下事件
  uint8_t release;  //释放事件
}key_scan_t;

key_scan_t key_scan[4];

display_time_t display_time;      
display_time_t last_time;       
timeInfo_t timeInfo;

//----------WIFI连接配置----------
//const char *ssid     = "your ssid";              // 连接WiFi名（此处使用XXX为示例）                                   
//const char *password = "your password";          // 连接WiFi密码（此处使用12345678为示例）
// const char *ssid     = "TP-LINK_468E";
// const char *password = "fangdayu998";
 const char *ssid     = "ChinaNet-rpqr";
 const char *password = "13962594159";

//WifiUDP对象，用于与NTP服务器通信 "pool.ntp.org" ntp服务器地址  8*
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 60 * 60;
const int daylightOffset_sec = 0;

int en_12H_or_24H_Press = 0;      
int en_date_Press = 0;
int index_led_color_Press = 0;
int index_tft_pic_press= 0;
unsigned long previousMillis = 0;
static uint8_t count = 0;

/*函数名称：全局初始化函数*/
void global_init()
{
  int i;
  pinMode(buttonCS1,OUTPUT);
  pinMode(buttonCS2,OUTPUT);
  pinMode(buttonCS3,OUTPUT);
  pinMode(buttonCS4,OUTPUT);
  pinMode(buttonCS5,OUTPUT);
  pinMode(buttonCS6,OUTPUT);

  pinMode(buttonKEY1,INPUT);
  pinMode(buttonKEY2,INPUT);
  pinMode(buttonKEY3,INPUT);
  pinMode(buttonKEY4,INPUT);

  buttonKEY[0] = buttonKEY1;
  buttonKEY[1] = buttonKEY2;
  buttonKEY[2] = buttonKEY3;
  buttonKEY[3] = buttonKEY4;

  for(i=0;i<4;i++)
  {
    key_scan[i].status =0;
    key_scan[i].count = 0;
    key_scan[i].release = 0;
  }
  memset(&last_time,0xff,sizeof(display_time_t));
}

/*函数名称：按键状态函数*/
void get_key_status()
{
  uint8_t i;
  for(i=0;i<4;i++)
  {
    if(digitalRead(buttonKEY[i]) == 0)
    {

      if(key_scan[i].status == 0 )
      {

        key_scan[i].count++;
        if(key_scan[i].count >= 5)
        {

           key_scan[i].count = 5;  
           key_scan[i].status = 1;          
        }
      }
    }
    else
    {
        if(key_scan[i].count>0){
          key_scan[i].count--;
          if (key_scan[i].status == 1)
          {
            if(key_scan[i].count == 0)
            {
                key_scan[i].status = 0;
                key_scan[i].release = 1;
            }      
          }
        }


    }
  }
}

/*函数名称：按键动作函数*/
void gloabal_key_process()
{
    uint8_t i=0,index = 100;
    for(i=0;i<4;i++) 
    {
        if(key_scan[i].release > 0)
        {
           key_scan[i].release = 0;
           index = i;
           i = 100; 
        }  
    }
    if(index == 100) return;
    if(index == 0)  
    {
        index_led_color_Press ++ ;
        if(index_led_color_Press > 6)
        {
            index_led_color_Press = 0;
        }
    }
    else if(index == 1) 
    {
      if(en_12H_or_24H_Press)
        en_12H_or_24H_Press = 0;
      else
        en_12H_or_24H_Press = 1; 
    }
    else if(index == 2)
    {
        memset(&last_time,255,sizeof(display_time_t));
        index_tft_pic_press++;
        if(index_tft_pic_press >= 4)
        {
          index_tft_pic_press = 0;
        }
    }
    else if(index == 3)
    {


    }  
}

/*函数名称：tft片选信号*/
void tft_cs_digital_write_status(uint8_t channel,uint8_t val)
{
  if(val == HIGH)
  {
    digitalWrite(buttonCS1,HIGH);
    digitalWrite(buttonCS2,HIGH);
    digitalWrite(buttonCS3,HIGH);
    digitalWrite(buttonCS4,HIGH);
    digitalWrite(buttonCS5,HIGH);
    digitalWrite(buttonCS6,HIGH);
  }
  else
  {
    switch (channel)
    {
      case 0:
        digitalWrite(buttonCS1,LOW);
        digitalWrite(buttonCS2,HIGH);
        digitalWrite(buttonCS3,HIGH);
        digitalWrite(buttonCS4,HIGH);
        digitalWrite(buttonCS5,HIGH);
        digitalWrite(buttonCS6,HIGH);
      break;
      case 1:
        digitalWrite(buttonCS1,HIGH);
        digitalWrite(buttonCS2,LOW);
        digitalWrite(buttonCS3,HIGH);
        digitalWrite(buttonCS4,HIGH);
        digitalWrite(buttonCS5,HIGH);
        digitalWrite(buttonCS6,HIGH);  
      break;    
      case 2:
        digitalWrite(buttonCS1,HIGH);
        digitalWrite(buttonCS2,HIGH);
        digitalWrite(buttonCS3,LOW);
        digitalWrite(buttonCS4,HIGH);
        digitalWrite(buttonCS5,HIGH);
        digitalWrite(buttonCS6,HIGH);      
      break;
      case 3:
        digitalWrite(buttonCS1,HIGH);
        digitalWrite(buttonCS2,HIGH);
        digitalWrite(buttonCS3,HIGH);
        digitalWrite(buttonCS4,LOW);
        digitalWrite(buttonCS5,HIGH);
        digitalWrite(buttonCS6,HIGH);
      break;
      case 4:
        digitalWrite(buttonCS1,HIGH);
        digitalWrite(buttonCS2,HIGH);
        digitalWrite(buttonCS3,HIGH);
        digitalWrite(buttonCS4,HIGH);
        digitalWrite(buttonCS5,LOW);
        digitalWrite(buttonCS6,HIGH); 
      break;     
      case 5:
        digitalWrite(buttonCS1,HIGH);
        digitalWrite(buttonCS2,HIGH);
        digitalWrite(buttonCS3,HIGH);
        digitalWrite(buttonCS4,HIGH);
        digitalWrite(buttonCS5,HIGH);
        digitalWrite(buttonCS6,LOW);      
      break;            
      default:
      break;
    }
  }

}

/*函数名称：初始化图片刷新*/
void tft_display_init_image()
{
    tft_cs_digital_write_status(0,LOW);
    tft.pushImage(0, 0, 135, 240, ironman_135240);
    tft_cs_digital_write_status(0,HIGH);
    delay(10);
    tft_cs_digital_write_status(1,LOW);
    tft.pushImage(0, 0, 135, 240, thor_135240);
    tft_cs_digital_write_status(1,HIGH);
    delay(10);
    tft_cs_digital_write_status(2,LOW);
    tft.pushImage(0, 0, 135, 240, captain_america_135240);
    tft_cs_digital_write_status(2,HIGH);
    delay(10);
    tft_cs_digital_write_status(3,LOW);
    tft.pushImage(0, 0, 135, 240, batman_135240);
    tft_cs_digital_write_status(3,HIGH); 
    delay(10);   
    tft_cs_digital_write_status(4,LOW);
    tft.pushImage(0, 0, 135, 240, superman_135240);
    tft_cs_digital_write_status(4,HIGH);
    delay(10);
    tft_cs_digital_write_status(5,LOW);
    tft.pushImage(0, 0, 135, 240, hulk_135240);
    tft_cs_digital_write_status(5,HIGH);
}

/*函数名称：刷新辉光管图片*/
void tft_display_image(uint8_t channel,uint8_t number)
{
  tft_cs_digital_write_status(channel,LOW);
  if(index_tft_pic_press == 0)
  {
    switch (number)
    {
    case 0:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_0);
      break;
    case 1:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_1);
      break;
    case 2:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_2);
      break;
    case 3:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_3);
      break;
    case 4:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_4);
      break;
    case 5:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_5);
      break;
    case 6:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_6);
      break;
    case 7:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_7);
      break;
    case 8:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_8);
      break;
    case 9:
      tft.pushImage(0, 0, 135, 240, GlowTube_135240_9);
      break;                   
    default:
      break;
    }  
  }
  else if(index_tft_pic_press == 1)
  {
    switch (number)
    {
      case 0:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_0);
        break;
      case 1:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_1);
        break;
      case 2:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_2);
        break;
      case 3:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_3);
        break;
      case 4:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_4);
        break;
      case 5:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_5);
        break;
      case 6:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_6);
        break;
      case 7:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_7);
        break;
      case 8:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_8);
        break;
      case 9:
        tft.pushImage(0, 0, 135, 240, Rainbow_135240_9);
        break;                   
      default:
        break;
    } 
  }
  else if(index_tft_pic_press == 2)
  {
    switch (number)
    {
      case 0:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_0);
        break;
      case 1:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_1);
        break;
      case 2:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_2);
        break;
      case 3:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_3);
        break;
      case 4:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_4);
        break;
      case 5:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_5);
        break;
      case 6:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_6);
        break;
      case 7:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_7);
        break;
      case 8:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_8);
        break;
      case 9:
        tft.pushImage(0, 0, 135, 240, Colorful_135240_9);
        break;                   
      default:
        break;
    }
  }
else if(index_tft_pic_press == 3)
  {
    switch (number)
    {
      case 0:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_0);
        break;
      case 1:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_1);
        break;
      case 2:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_2);
        break;
      case 3:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_3);
        break;
      case 4:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_4);
        break;
      case 5:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_5);
        break;
      case 6:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_6);
        break;
      case 7:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_7);
        break;
      case 8:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_8);
        break;
      case 9:
        tft.pushImage(0, 0, 135, 240, Lattice_135240_9);
        break;                   
      default:
        break;
    }
  }  
  delay(1);
  tft_cs_digital_write_status(channel,HIGH);
}

/*函数名称：Clock更新函数*/
void gloabal_clock_display_process()
{
    timeInfo.hour = rtc.getHour();
    if(en_12H_or_24H_Press == 1)           //12小时制
    {
        if(timeInfo.hour > 12) 
            timeInfo.hour -= 12;
    }
    display_time.hour_h = timeInfo.hour/10;
    if(last_time.hour_h != display_time.hour_h)
    {
        tft_display_image(0,display_time.hour_h);
        last_time.hour_h = display_time.hour_h;
    }
    display_time.hour_l = timeInfo.hour%10;
    if(last_time.hour_l != display_time.hour_l)
    {
        tft_display_image(1,display_time.hour_l);
        last_time.hour_l = display_time.hour_l;
    }
    timeInfo.minute = rtc.getMinute();
    display_time.minute_h = timeInfo.minute/10;
    if(last_time.minute_h != display_time.minute_h)
    {
        tft_display_image(2,display_time.minute_h);
        last_time.minute_h = display_time.minute_h;
    }
    display_time.minute_l = timeInfo.minute%10;
    if(last_time.minute_l != display_time.minute_l)
    {
        tft_display_image(3,display_time.minute_l);
        last_time.minute_l = display_time.minute_l;
    } 
    timeInfo.second = rtc.getSecond();
    display_time.second_h = timeInfo.second/10;
    if(last_time.second_h != display_time.second_h)
    {
        tft_display_image(4,display_time.second_h);
        last_time.second_h = display_time.second_h;
    }
    display_time.second_l = timeInfo.second%10;
    if(last_time.second_l != display_time.second_l)
    {
        tft_display_image(5,display_time.second_l);
        last_time.second_l = display_time.second_l;
    }              
}

/*函数名称：wled显示函数*/
void gloabal_led_display_process()
{
  switch (index_led_color_Press)
  {
  case 0:
    fill_solid(leds, NUM_LEDS, CRGB::Black);
    break;
  case 1:
    fill_solid(leds, NUM_LEDS, CRGB::Red);
    break;    
  case 2:
    fill_solid(leds, NUM_LEDS, CRGB::Orange);
    break;  
  case 3:
    fill_solid(leds, NUM_LEDS, CRGB::Yellow);
    break;
  case 4 :
    fill_solid(leds, NUM_LEDS, CRGB::Green);
    break; 
  case 5 :
    fill_solid(leds, NUM_LEDS, CRGB::Blue);
    break; 
  case 6 :
    fill_solid(leds, NUM_LEDS, CRGB::Purple);
    break;            
  default:
    break;
  }
  FastLED.show();
}


void setup() {

  uint8_t wifi_count = 30;
  struct tm timeinfo;
  Serial.begin(9600);
  global_init();

  tft.init();
  tft.setRotation(0);
  tft.fillScreen(TFT_GREEN);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
    wifi_count -- ;
    if(wifi_count == 0)
      break;
  }
  if(wifi_count > 0)
  {
    Serial.println("WiFi connected!");
    Serial.println(WiFi.localIP());
  }
  else
  {
    Serial.println("WiFi disconnected!");
  }

  
  tft.setSwapBytes(true);             //使图片颜色由RGB->BGR
  tft_display_init_image();

  LEDS.addLeds<WS2812, LED_DT, GRB>(leds, NUM_LEDS);  // 初始化光带  
  FastLED.setBrightness(128);                            // 设置光带亮度
  Wire.begin(21,22);
  rtc.RX8025_init();
  Serial.println("RX8025 Init finish!");

  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);//初始化NTP客户端

  if(getLocalTime(&timeinfo) == true)
  {
    Serial.printf("timeinfo = %02d-%02d-%02d %02d:%02d:%02d ",(timeinfo.tm_year+1900)%100, timeinfo.tm_mon+1 ,timeinfo.tm_mday ,timeinfo.tm_hour,timeinfo.tm_min,timeinfo.tm_sec);
    Serial.println("getLocalTime finish!");
    rtc.setRtcTime(timeinfo.tm_sec, timeinfo.tm_min, timeinfo.tm_hour,timeinfo.tm_wday,timeinfo.tm_mday,timeinfo.tm_mon+1, (timeinfo.tm_year+1900)%100);
  }
  else
  {
    Serial.println("Failed to obtain time");
  }
  WiFi.disconnect();
}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis > 10) {
      previousMillis = currentMillis;
      get_key_status();
      gloabal_key_process();
      if(count ++ >=20)
      {
        gloabal_clock_display_process();
        gloabal_led_display_process();
        count = 0;
      }
    } 
  }














